#define _CRT_SECURE_NO_WANINGS 1
#pragma warning(disable: 4996)
#include<stdlib.h>
#include<assert.h>
#include<stdio.h>
typedef int QeDataType;
typedef struct QueueNode
{
	struct QueueNode* next;
	QeDataType data;
}Qnode;
typedef struct Queue
{
	Qnode* head;
	Qnode* back;
}Qe;

Qnode* CreateNode(QeDataType x)
{
	Qnode* newnode = (Qnode*)malloc(sizeof(Qnode));
	newnode->data = x;
	newnode->next = NULL;
	return newnode;
}
void QueueInit(Qe* q)
{
	assert(q);
	Qnode* newnode = CreateNode(-1);
	q->head = newnode;
	q->back = newnode;
}
void QueueDestroy(Qe* q)
{
	assert(q);
	Qnode* cur = q->head->next;
	while (cur)
	{
		Qnode* next = cur->next;
		free(cur);
		cur = next;
	}
	/*free(q->back);*/
	q->back = NULL;
	free(q->head);
	q->head = NULL;
}
void Queuepush(Qe* q, QeDataType x)
{
	assert(q);
	Qnode* newnode = CreateNode(x);
	q->back->next = newnode;
	q->back = newnode;
}
void QueuePop(Qe* q)
{
	assert(q);
	assert(q->head->next);

	Qnode* next = q->head->next;
	q->head->next = next->next;
	free(next);
	next = NULL;
	if (q->head->next == NULL)
	{
		q->back = q->head;
		q->back->next = NULL;
	}
}
QeDataType QueueFront(Qe* q)
{
	assert(q);
	assert(q->head->next);
	return q->head->next->data;
}
QeDataType QueueBack(Qe* q)
{
	assert(q);
	assert(q->head->next);
	return q->back->data;
}
int QueueSize(Qe* q)
{
	Qnode* size = q->head->next;
	int num = 0;
	while (size)
	{
		size = size->next;
		num++;
	}
	return num;
}
bool QueueEmpty(Qe* q)
{
	return q->head->next == NULL;
}

typedef struct {
	int* a;
	int front;
	int rear;
	int k;
} MyCircularQueue;


MyCircularQueue* myCircularQueueCreate(int k) {
	MyCircularQueue* obj = (MyCircularQueue*)malloc(sizeof(MyCircularQueue));
	obj->a = (int*)malloc(sizeof(int) * (k + 1));
	obj->k = k;
	obj->front = 0;
	obj->rear = 0;
	return obj;
}
bool myCircularQueueIsEmpty(MyCircularQueue* obj) {
	return obj->front == obj->rear;
}

bool myCircularQueueIsFull(MyCircularQueue* obj) {
	return (obj->rear + 1) % (obj->k + 1) == obj->front;
}
bool myCircularQueueEnQueue(MyCircularQueue* obj, int value) {
	if (myCircularQueueIsFull(obj))
	{
		return false;
	}
	obj->rear %= obj->k + 1;
	obj->a[obj->rear] = value;

	obj->rear++;
	return true;
}

bool myCircularQueueDeQueue(MyCircularQueue* obj) {
	if (myCircularQueueIsEmpty(obj))
	{
		return false;
	}
	obj->front %= obj->k + 1;
	obj->front++;
	return true;
}

int myCircularQueueFront(MyCircularQueue* obj) {
	if (myCircularQueueIsEmpty(obj))
	{
		return -1;
	}
	return obj->a[obj->front];
}

int myCircularQueueRear(MyCircularQueue* obj) {
	if (myCircularQueueIsEmpty(obj))
	{
		return -1;
	}
	//if (obj->rear == 0)
	//{
	//	return obj->a[obj->k];
	//}
	//else
	//{
	//	return obj->a[obj->rear - 1];
	//}
	return obj->a[((obj->rear - 1) + (obj->k + 1)) % (obj->k + 1)];
}



void myCircularQueueFree(MyCircularQueue* obj) {
	free(obj->a);
	obj->a = NULL;
	free(obj);
	obj = NULL;
}

int main()
{
	MyCircularQueue* mq = myCircularQueueCreate(2);
	myCircularQueueEnQueue(mq, 1);
	myCircularQueueEnQueue(mq, 2);
	myCircularQueueEnQueue(mq, 3);
	myCircularQueueEnQueue(mq, 4);
	printf("%d", myCircularQueueRear(mq));
	return 0;
}